package com.study.util;

import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis基本数据类型
 * string,list,hash,set,zset,geo,hyperloglog
 * geo是位图正常不怎么使用
 * hyperloglog主要用作计数器
 * @author ytj
 * @date 2021/11/4
 */
@Component
public class RedisUtil {
    @Resource(name = "redisTemplate")
    private RedisTemplate redisTemplate;

    //string
    /**
     * 设置
     * */
    public void setString(Object key,Object value){
        this.redisTemplate.opsForValue().set(key,value);
    }

    /**
     * 设置值添加过期时间
     * */
    public void setString(Object key,Object value,Long time){
        this.redisTemplate.opsForValue().set(key,value,time, TimeUnit.SECONDS);
    }

    public Object get(Object key){
        return this.redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取字符串的子字符串
     * */
    public String get(Object key,Long start,Long end){
        return this.redisTemplate.opsForValue().get(key,start,end);
    }

    /**
     * 加一
     * */
    public Long addInter(Object key){
        return this.redisTemplate.opsForValue().increment(key);
    }

    /**
     * 加增量
     * */
    public Long addInterValue(Object key,Long value){
        return this.redisTemplate.opsForValue().increment(key,value);
    }

    /**
     * 减一
     * */
    public Long decr(Object key){
        return this.redisTemplate.opsForValue().decrement(key);
    }

    /**
     * 减固定值
     * */
    public Long decrValue(Object key,Long value){
        return this.redisTemplate.opsForValue().decrement(key,value);
    }

    //list
    /**
     * 右边插入
     * */
    public void setListRight(Object key,Object value){
        this.redisTemplate.opsForList().rightPush(key,value);
    }

    /**
     * 在keyValue的右边插入
     * */
    public void setListRightData(Object key,Object keyValue,Object value){
        this.redisTemplate.opsForList().rightPush(key,keyValue,value);
    }

    /**
     * 在右边插入多个
     * */
    public void setListRightMore(Object key,Object... value){
        this.redisTemplate.opsForList().rightPushAll(key,value);
    }

    /**
     * 左边插入
     * */
    public void setListLeft(Object key,Object value){
        this.redisTemplate.opsForList().leftPush(key,value);
    }

    /**
     * 在keyvalue值左边插入
     * */
    public void setListLeftData(Object key,Object keyValue,Object value){
        this.redisTemplate.opsForList().rightPush(key,keyValue,value);
    }

    /**
     * 在左边插入多个
     * */
    public void setListLeftMore(Object key,Object... value){
        this.redisTemplate.opsForList().leftPushAll(key,value);
    }

    /**
     * 在某个位置插入
     * */
    public void setListIndex(Object key,Object value,int index){
        this.redisTemplate.opsForList().set(key,index,value);
    }

    /**
     * 获取左边
     * */
    public Object getListLeft(Object key){
        return this.redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 获取右边
     * */
    public Object getListRight(Object key){
        return this.redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 获取范围
     * */
    public List getList(Object key, int start, int end){
        return this.redisTemplate.opsForList().range(key,start,end);
    }

    /**
     * 删除
     * */
    public void remove(Object key,Object value,int count){
        this.redisTemplate.opsForList().remove(key,count,value);
    }

    /**
     * 获取长度
     * */
    public Long getSize(Object key){
        return this.redisTemplate.opsForList().size(key);
    }

    //set
    /**
     * 插入
     * */
    public void setSet(Object key,Object... value){
        this.redisTemplate.opsForSet().add(key,value);
    }

    /**
     * 获取值
     * */
    public Set getSet(Object key){
        return this.redisTemplate.opsForSet().members(key);
    }

    /**
     * 弹出值
     * */
    public Object popSet(Object key){
        return this.redisTemplate.opsForSet().pop(key);
    }

    /**
     * 弹出固定长度值
     * */
    public List popLongSet(Object key,Long count){
        return this.redisTemplate.opsForSet().pop(key,count);
    }

    /**
     * 将value替换为newValue
     * */
    public void moveSet(Object key,Object value,Object newValue){
        this.redisTemplate.opsForSet().move(key,value,newValue);
    }

    /**
     * 删除
     * */
    public void removeSet(Object key,Object... value){
        this.redisTemplate.opsForSet().remove(key,value);
    }

    public Long scanSize(Object key){
        return this.redisTemplate.opsForSet().size(key);
    }
    //map
    /**
     * 新增
     * */
    public void addMap(Object key,Object hashKey,Object value){
        this.redisTemplate.opsForHash().put(key,hashKey,value);
    }

    /**
     * 新增
     * */
    public void addAllMap(Object key, Map map){
        this.redisTemplate.opsForHash().putAll(key,map);
    }

    /**
     * 获取
     * */
    public Object getMap(Object key,Object hashKey){
        return this.redisTemplate.opsForHash().get(key,hashKey);
    }

    /**
     * 删除
     * */
    public void delMap(Object key,Object... hashKey){
        this.redisTemplate.opsForHash().delete(key,hashKey);
    }

    /**
     * 获取key值
     * */
    public Object getMapKeys(Object key){
        return this.redisTemplate.opsForHash().keys(key);
    }

    /**
     * 是否包含key
     * */
    public boolean flgMapKey(Object key,Object hashKey){
        return this.redisTemplate.opsForHash().hasKey(key,hashKey);
    }

    /**
     * 获取长度
     * */
    public Long getMapSize(Object key){
        return this.redisTemplate.opsForHash().size(key);
    }

    //zset
    /**
     * 新增
     * */
    public boolean addZset(Object key,Object value,Long score){
        boolean flg=this.redisTemplate.opsForZSet().add(key,value,score);
        return flg;
    }

    /**
     * 新增
     * */
    public long addZsetAll(Object key, Set<ZSetOperations.TypedTuple> tupe){
        long count=this.redisTemplate.opsForZSet().add(key,tupe);
        return count;
    }

    /**
     * 获取
     * */
    public Set getZset(Object key,Long start,Long end){
        return this.redisTemplate.opsForZSet().range(key,start,end);
    }

    /**
     * 依据分数获取
     * */
    public Set getZsetByScore(Object key,double min,double max){
        return this.redisTemplate.opsForZSet().rangeByScore(key,min,max);
    }

    /**
     * 依据分数获取
     * */
    public Set getRangeByScore(Object key,double min,double max,int offset,int count){
        return this.redisTemplate.opsForZSet().rangeByScore(key,min,max,offset,count);
    }

    /**
     * 依据分值获取长度
     * */
    public long getZsetSizeByScore(Object key,double min,double max){
        return this.redisTemplate.opsForZSet().count(key,min,max);
    }

    /**
     * 获取长度
     * */
    public long getZsetSize(Object key){
        return this.redisTemplate.opsForZSet().size(key);
    }

    /**
     * 删除
     * */
    public void delZset(Object key,Object... value){
        this.redisTemplate.opsForZSet().remove(key,value);
    }

    /**
     * 获取分值
     * */
    public Double getScore(Object key,Object value){
        return this.redisTemplate.opsForZSet().score(key,value);
    }

    //位图
    /**
     *添加
     * @Param key 主键
     * @param name 名称
     * @param x 经度
     * @param y 纬度
     * */
    public Long addGeo(Object key,String name,double x,double y){
        Point point=new Point(x,y);
        RedisGeoCommands.GeoLocation geoLocation=new RedisGeoCommands.GeoLocation(name,point);
        Long count=this.redisTemplate.opsForGeo().add(key,geoLocation);
        return count;
    }

    /**
     * 删除
     * @param key 主键
     * @param member 成员
     * */
    public Long delGeo(Object key,Object... member){
        Long count=this.redisTemplate.opsForGeo().remove(key,member);
        return count;
    }

    /**
     * 获取指定key的经纬度信息
     * @param key
     * @param member 成员信息
     * */
    public List<Point> getPoint(Object key,Object... member){
        List<Point> list=this.redisTemplate.opsForGeo().position(key,member);
        return list;
    }

    /**
     * 返回两个地方距离
     * @param key
     * @param member1 成员1
     * @param member2 成员2
     * */
    public Distance getDist(Object key,Object member1,Object member2){
        Distance distance=this.redisTemplate.opsForGeo().distance(key,member1,member2);
        return distance;
    }

    //计数器
    /**
     * 添加计数器
     * @param key
     * */
    public Long addHyperLog(Object key,Object... values){
        Long count=this.redisTemplate.opsForHyperLogLog().add(key,values);
        return count;
    }


    /**
     * 获取计数器中值长度
     * */
    public Long getHyperLogCount(Object... key){
        Long count=this.redisTemplate.opsForHyperLogLog().size(key);
        return count;
    }

    /**
     * 获取计数器交际
     * */
    public Long unionHyper(Object distinction,Object... sourceKyes){
        Long count=this.redisTemplate.opsForHyperLogLog().union(distinction,sourceKyes);
        return count;
    }

    /**
     * 删除计数器
     * */
    public void delHyperLog(Object key){
        this.redisTemplate.opsForHyperLogLog().delete(key);
    }


}
